package com.gusto.engine.clusterant.algorithms.kmeansclustering;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.gusto.engine.clusterant.model.Point;

/**
 * <p>A set of {@link Point}.</p>
 * 
 * @author amokrane.belloui@gmail.com
 *
 */
public class Cluster {
	
	private Logger log = Logger.getLogger(getClass());
	
	private int id;
	private Double row, col;
	private List<Point> components;
	  
	public Cluster(int id, Double row, Double col) {
		this.id = id;
		this.row = row;
		this.col = col;
		components = new ArrayList<Point>();
	} 
	
	public String toString() {
		String res = "Cluster (" + (Math.round(row * 100) / 100) + "-" + (Math.round(col * 100) / 100) + ")  |";
		for (Point p : components) {
			res += p.getObject() + "|";
		}
		return res;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public Double getRow() {
		return row;
	}
	public void setRow(Double row) {
		this.row = row;
	}
	
	public Double getCol() {
		return col;
	}
	public void setCol(Double col) {
		this.col = col;
	}
	
	public List<Point> getComponents() {
		return components;
	}
	
	public Double getQuality() {
		int count = 0;
		double distance = 0D;
		for (Point point : components) {
			double d = Math.sqrt( 
				Math.pow(this.getRow() - point.getRow(), 2) + 
				Math.pow(this.getCol() - point.getCol(), 2) 
			);
			distance += d;
			count ++;
		}
		// Using a power of count, to improve quality for big clusters
		return (distance / Math.pow(count, 1.35));
	}
	
	public void computeCenter() {
		double newrow = 0;
		double newcol = 0;
		
		for (Point p : components) {
			newrow += p.getRow();
			newcol += p.getCol();
		}
		newrow = newrow/components.size();
		newcol = newcol/components.size();
		
		this.row = newrow;
		this.col = newcol;
		log.debug("Computing center of Cluster ... " + row + "-" + col);
	}
	
	public boolean isEmpty() {
		return this.components.size() == 0;
	}
	
	public void emptyPoints() {
		this.components.clear();
	}
	
}
